package view.views;

import globalOperations.MarkupMethods;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor;
import org.eclipse.jdt.ui.JavaElementLabelProvider;
import org.eclipse.jdt.ui.StandardJavaElementContentProvider;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.forms.widgets.ExpandableComposite;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.ScrolledForm;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.part.ViewPart;

import singleton.Singleton;
import singleton.StoredImages;
import swtElements.Form;
import swtElements.MyComposite;
import swtElements.MySection;
import swtElements.MyToolBar;
import view.listener.AdaptListener;
import view.listener.ButtonListener;
import view.listener.CommentListener;
import view.listener.EditListener;
import view.listener.InfoListener;
import controller.data.Comment;
import controller.data.fundamental.TabItemCategory;
import controller.data.readDocumentation.ReadDocumentationRequest;
import controller.data.readDocumentation.ReadDocumentationResponse;

@SuppressWarnings("restriction")
public class CSADView extends ViewPart implements ISelectionListener {

	public TabFolder tabfolder; // Der Tabfolder
	public static ToolBar toolbarDoku; // Toolbar von den Item's der Doku
	public String idForDoc;
	public static List<ReadDocumentationResponse> listOfData;// Doc aus der DB
	public static String searchString; // Suchabfrage für DB
	private IEditorPart editorDoc; // Editor der Dokumentation
	public IEditorPart editorCom; // Editor der Kommentare
	// Dokumentation
	public Text textAddTab;
	public int position;
	public boolean getStarted;
	public boolean newDoc;
	private IJavaElement currentElement;

	/**
	 * The constructor.
	 */
	public CSADView() {
		getStarted = false;
		position = -1;
		idForDoc = "";
		Singleton.getInstance().setEmptyTab(new TabItemCategory("", ""));
		Singleton.getInstance().setTabentrys(new TabEntrys());
		Singleton.getInstance().setSelectedTab(
				Singleton.getInstance().getEmptyTab());
		listOfData = new ArrayList<ReadDocumentationResponse>(); // Dokumentationsausgabe
		searchString = ""; // Das Element wonach in der DB gesucht wird
	}

	public void putTabentryIntoBla(String tabEntry) {
		String categoryEntry = tabEntry.toLowerCase();
		categoryEntry = categoryEntry.replaceAll(" ", "_");
		TabEntrys tabETMP = Singleton.getInstance().getTabentrys();
		tabETMP.inputEntry(new TabItemCategory(tabEntry, categoryEntry));
		Singleton.getInstance().setTabentrys(tabETMP);
	}

	/**
	 * It's the main method of the class, it's called, when you started the view
	 */
	@Override
	public void createPartControl(Composite parent) {

		getSite().getWorkbenchWindow().getSelectionService()
				.addPostSelectionListener(this);

		// Tabfolder

		tabfolder = new TabFolder(parent, SWT.BOTTOM);
		tabfolder.addSelectionListener(new AdaptListener(this));

		// Tabs

		int size = Singleton.getInstance().getTabentrys().getSize();
		TabEntrys tabETMP = Singleton.getInstance().getTabentrys();
		for (int i = 0; i < size; i++) {
			TabItem tabitem = new TabItem(tabfolder, SWT.LEFT_TO_RIGHT);
			tabitem.setText(tabETMP.getEntrys(i).getTabItemName());
			if (i == 0) {
				TabItemCategory selTabTMP = Singleton.getInstance()
						.getSelectedTab();
				selTabTMP.setCategoryName(tabETMP.getEntrys(i)
						.getCategoryName());

				selTabTMP.setTabItemName(tabETMP.getEntrys(i).getTabItemName());

				Singleton.getInstance().setSelectedTab(selTabTMP);
			}
		}

		getSite().getWorkbenchWindow().getSelectionService()
				.addSelectionListener(this);

		// Close all open editors

		IEditorReference[] editors = getSite().getPage().getEditorReferences();
		IEditorReference[] ref = new IEditorReference[2];
		for (int i = 0; i < editors.length; i++) {
			String tmp01 = editors[i].getName();
			if (tmp01.compareTo("muster.min") == 0) {
				ref[0] = editors[i];
			}
			if (tmp01.compareTo("muster.mene") == 0) {
				ref[1] = editors[i];
			}
		}
		if (ref[0] != null && ref[1] != null)
			getSite().getPage().closeEditors(ref, false);
		else if (ref[0] != null) {
			IEditorReference[] refdel = new IEditorReference[1];
			refdel[0] = ref[0];
			getSite().getPage().closeEditors(refdel, false);
		} else if (ref[1] != null) {
			IEditorReference[] refdel = new IEditorReference[1];
			refdel[0] = ref[1];
			getSite().getPage().closeEditors(refdel, false);

		}
	}

	/**
	 * Passing the focus request to the form.
	 */
	@Override
	public void setFocus() {
		tabfolder.setFocus();
	}

	/**
	 * Disposes the toolkit
	 */
	@Override
	public void dispose() {
		tabfolder.dispose();
		getSite().getWorkbenchWindow().getSelectionService()
				.removeSelectionListener(this);
		super.dispose();
	}

	/**
	 * If the selection element is changed in the editor this method is called
	 */
	public void selectionChanged(IWorkbenchPart part, ISelection selection) {

		IJavaElement element = null;
		try {
			if (part instanceof JavaEditor
					&& selection instanceof ITextSelection) {
				IJavaElement[] elements = TextSelectionConverter.codeResolve(
						(JavaEditor) part, (ITextSelection) selection);
				if (elements != null && elements.length > 0) {
					element = elements[0];
				}
			}
		} catch (JavaModelException e) {
			e.printStackTrace();
		}
		// If a element is selected in the editor
		if (element != null) {
			if (element.getElementType() == 9 || element.getElementType() == 7
					|| element.getElementType() == 8
					|| element.getElementType() == 14) {
				if (getStarted == false) getStarted = true;
				currentElement = element;
				searchString = JavaElementSpecifier
						.getFullSpecification(element);
				Singleton.getInstance().setSearchString(searchString);
				listOfData = Singleton.getInstance().getUseCaseController()
						.readDocumentation(
								new ReadDocumentationRequest(Singleton
										.getInstance().getSelectedTab()
										.getCategoryName(), searchString));
				createTabView();
			}
		}
	}

	/**
	 * The method is called, if you want to open a editor
	 * @param editor
	 * 			It's the DocumentEditor or the CommentEditor
	 * @param file
	 * 			The location of the editor
	 * @return
	 * 		the open editor
	 */
	public IEditorPart openEditor(IEditorPart editor, String file) {

		Singleton.getInstance().setResponse("");

		getSite().getWorkbenchWindow().getActivePage().closeEditor(editor,
				false);
		File fileToOpen = new File(file);
		if (fileToOpen.exists() && fileToOpen.isFile()) {
			IFileStore fileStore = EFS.getLocalFileSystem().getStore(
					fileToOpen.toURI());
			IWorkbenchPage page = PlatformUI.getWorkbench()
					.getActiveWorkbenchWindow().getActivePage();
			try {
				editor = IDE.openEditorOnFileStore(page, fileStore);
			} catch (PartInitException e) {
				// Put your exception handler here if you wish to
			}
		} else {
			// Do something if the file does not exist
			try {
				// Create file
				FileWriter fstream = new FileWriter(file);
				BufferedWriter out = new BufferedWriter(fstream);
				// Close the output stream
				out.close();
			} catch (Exception e) {// Catch exception if any
				System.err.println("Error: " + e.getMessage());
			}
			IFileStore fileStore = EFS.getLocalFileSystem().getStore(
					fileToOpen.toURI());
			IWorkbenchPage page = PlatformUI.getWorkbench()
					.getActiveWorkbenchWindow().getActivePage();
			try {
				editor = IDE.openEditorOnFileStore(page, fileStore);
			} catch (PartInitException e) {
				// Put your exception handler here if you wish to
			}
		}
		return editor;
	}

	/**
	 * Refresh the open editor
	 * @param editor
	 * 			DocumentEditor or CommentEditor
	 * @param file
	 * 			URL of the editor
	 * @return
	 * 		the open editor
	 */
	public IEditorPart refreshOrOpenEditor(IEditorPart editor, String file) {
		if (newDoc) {
			getSite().getWorkbenchWindow().getActivePage().closeEditor(editor,
					false);
			File fileToOpen = new File(file);
			if (fileToOpen.exists() && fileToOpen.isFile()) {
				IFileStore fileStore = EFS.getLocalFileSystem().getStore(
						fileToOpen.toURI());
				IWorkbenchPage page = PlatformUI.getWorkbench()
						.getActiveWorkbenchWindow().getActivePage();
				try {
					editor = IDE.openEditorOnFileStore(page, fileStore);
				} catch (PartInitException e) {
					// Put your exception handler here if you wish to
				}
			} else {
				// Do something if the file does not exist
				try {
					// Create file
					FileWriter fstream = new FileWriter(file);
					BufferedWriter out = new BufferedWriter(fstream);
					// Close the output stream
					out.close();
				} catch (Exception e) {// Catch exception if any
					System.err.println("Error: " + e.getMessage());
				}
				IFileStore fileStore = EFS.getLocalFileSystem().getStore(
						fileToOpen.toURI());
				IWorkbenchPage page = PlatformUI.getWorkbench()
						.getActiveWorkbenchWindow().getActivePage();
				try {
					editor = IDE.openEditorOnFileStore(page, fileStore);
				} catch (PartInitException e) {
					// Put your exception handler here if you wish to
				}
			}
		}
		return editor;
	}

	/**
	 * Shows the active editor again
	 * @param editor
	 * 			DocumentEditor or CommentEditor
	 */
	public void setActivePageBack(IEditorPart editor) {
		try {
			getSite().getWorkbenchWindow().getActivePage().openEditor(
					editor.getEditorInput(), editor.getEditorSite().getId());
		} catch (PartInitException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * This method creates the swt elements of a tabitem
	 */
	public void createTabView() {
		if (Singleton.getInstance().getSelectedTab().getTabItemName()
				.compareTo("JavaDoc") == 0) {
			if (getStarted) {
				FormToolkit toolkitView = new FormToolkit(tabfolder
						.getDisplay());
				Form formView = new Form(toolkitView, tabfolder);

				Browser javaDocBrowser = new Browser(formView.getBody(),
						SWT.NONE);
				javaDocBrowser.setLayoutData(new GridData(GridData.FILL_BOTH));
				Color docYellow = new Color(null, 255, 255, 225);
				String html = "<h3>" + searchString + "</h3>";
				String tmp = "test";
				try {
					tmp = currentElement.getAttachedJavadoc(null);
				} catch (JavaModelException e) {
					e.printStackTrace();
				}
				if (tmp != null)
					javaDocBrowser.setText(html + tmp);
				else
					javaDocBrowser.setText(html);
				javaDocBrowser.setBackground(docYellow);
				tabfolder.getSelection()[0].setControl(formView.getForm());
			}
		} else {
			if (getStarted) {
				FormToolkit toolkitView = new FormToolkit(tabfolder
						.getDisplay());
				Form formView = new Form(toolkitView, tabfolder);

				initTabWindow(toolkitView, formView.getForm());

				createMainBar(toolkitView, formView.getForm());

				if (listOfData != null && !listOfData.isEmpty()) {
					for (int i = 0; i < listOfData.size(); i++) {

						ReadDocumentationResponse docReadData = listOfData
								.get(i);

						createSectionDocumentation(toolkitView, formView.getForm(),
								docReadData, i);

						createSectionCommentation(toolkitView, formView.getForm(),
								docReadData, i);
					}
				}
				createPreviousAndNext(toolkitView, formView);
				
				tabfolder.getSelection()[0].setControl(formView.getForm());
			}
		}
	}

	/**
	 * 
	 * @param toolkitView
	 * @param form
	 */
	private void createPreviousAndNext(FormToolkit toolkitView,
			Form form) {
		MySection lastSection = new MySection(toolkitView, form, "", false, "", false);
		
		MyComposite lastComposite = new MyComposite(toolkitView, lastSection, 2, true);
		
		GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
		
		if(Singleton.getInstance().getUseCaseController().isFirstPage() == false){
			Button previous = new Button(lastComposite.getComposite(), SWT.NONE);
			previous.setText("Previous page");
			gridData.grabExcessHorizontalSpace = true;
			previous.setLayoutData(gridData);
			previous.addListener(SWT.Selection, new ButtonListener(this));
		}
		
		if(Singleton.getInstance().getUseCaseController().hasNextPage()){
			Button next = new Button(lastComposite.getComposite(), SWT.NONE);
			next.setText("Next page");
			gridData = new GridData(GridData.HORIZONTAL_ALIGN_END);
			gridData.grabExcessHorizontalSpace = true;
			next.setLayoutData(gridData);
			next.addListener(SWT.Selection, new ButtonListener(this));
		}
		
		lastSection.setClient(lastComposite);
	}

	private Section createSectionDocumentation(FormToolkit toolkitView,
			ScrolledForm formView, ReadDocumentationResponse docReadData,
			int pos) {
		Section sectionDoku = toolkitView.createSection(formView.getBody(),
				ExpandableComposite.TITLE_BAR | ExpandableComposite.EXPANDED);
		sectionDoku.setLayoutData(new GridData(GridData.FILL_BOTH));
		sectionDoku.setText(docReadData.getRevision().getHeader()+ " [" + docReadData.getRevision().getDate()+"]");
		Color black = new Color(null, 0, 0, 0);
		sectionDoku.setForeground(black);

		ToolBarManager toolBarManagerDoku = new ToolBarManager(SWT.FLAT);
		toolbarDoku = toolBarManagerDoku.createControl(sectionDoku);

		ToolItem itemInfo = new ToolItem(toolbarDoku, SWT.NONE);
		itemInfo.setImage(StoredImages.getInstance().getMyImageRegistry().get(
				"INFO"));
		itemInfo.addListener(SWT.Selection, new InfoListener(this, toolbarDoku,
				tabfolder.getShell(), pos));

		ToolItem itemEdit = new ToolItem(toolbarDoku, SWT.NONE);
		itemEdit.setImage(StoredImages.getInstance().getMyImageRegistry().get(
				"EDIT"));
		itemEdit.addListener(SWT.Selection, new EditListener(docReadData
				.getId(), this, Singleton.getInstance().getUseCaseController(),
				pos));

		sectionDoku.setTextClient(toolbarDoku);

		Composite clientDoku = toolkitView.createComposite(sectionDoku);

		GridLayoutFactory.swtDefaults().numColumns(1).margins(0, 0).applyTo(
				clientDoku);

		GridData gridBrowser = new GridData(GridData.FILL_BOTH);
		gridBrowser.minimumHeight = 100;

		Browser browserDoku = new Browser(clientDoku, SWT.NONE);
		browserDoku.setLayoutData(gridBrowser);
		browserDoku.setText(MarkupMethods.parseMarkUpToHTML(docReadData
				.getRevision().getContent()));
		sectionDoku.setClient(clientDoku);

		return sectionDoku;
	}

	private void createSectionCommentation(FormToolkit toolkitView,
			ScrolledForm formView, ReadDocumentationResponse docReadData,
			int pos) {
		Section sectionCommentation = toolkitView.createSection(formView
				.getBody(), ExpandableComposite.TWISTIE
				| ExpandableComposite.TITLE_BAR);
		sectionCommentation
				.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		sectionCommentation.setText(docReadData.getComments().size()
				+ " comments");

		Color black = new Color(null, 0, 0, 0);
		sectionCommentation.setForeground(black);

		GridLayout gridLayoutCommentation = new GridLayout();
		gridLayoutCommentation.numColumns = 1;

		Composite clientCommmentation = toolkitView
				.createComposite(sectionCommentation);

		GridLayoutFactory.swtDefaults().numColumns(1).margins(0, 0).applyTo(
				clientCommmentation);

		ToolBarManager toolBarManagerCommentation = new ToolBarManager(SWT.FLAT);
		ToolBar toolbarCommentation = toolBarManagerCommentation
				.createControl(sectionCommentation);

		ToolItem itemComment = new ToolItem(toolbarCommentation, SWT.NONE);
		itemComment.setImage(StoredImages.getInstance().getMyImageRegistry()
				.get("COM"));

		sectionCommentation.setTextClient(toolbarCommentation);

		GridData gridCom = new GridData(GridData.FILL_BOTH);
		gridCom.minimumHeight = 150;

		Browser browserCommentation = new Browser(clientCommmentation, SWT.NONE);
		browserCommentation.setLayoutData(gridCom);
		StringBuilder builder = new StringBuilder();
		if (docReadData.getComments() != null) {
			for (int j = 0; j < docReadData.getComments().size(); j++) {
				Comment com = docReadData.getComments().get(j);
				builder.append("<hr>");
				if (com.getFirstname().trim() != ""
						|| com.getLastname().trim() != "") {
					builder.append("<strong>");
					String name = "";
					if (com.getFirstname().compareTo("") == 0
							&& com.getLastname().compareTo("") == 0)
						name = "No Name:";
					else if (com.getFirstname().compareTo("") != 0)
						name = com.getFirstname() + " " + com.getLastname();
					else
						name = com.getLastname();
					builder.append(name);
					builder.append("</strong>");
					builder.append(" [");
					builder.append(com.getDate());
					builder.append("]");
					builder.append("<br>");
				}
				builder.append("");
				builder.append(com.getContent());
			}
		}

		browserCommentation.setText(builder.toString());

		sectionCommentation.setClient(clientCommmentation);

		itemComment.addListener(SWT.Selection, new CommentListener(docReadData
				.getId(), this, Singleton.getInstance().getUseCaseController(),
				pos));
	}

	private void initTabWindow(FormToolkit toolkitView, ScrolledForm formView) {
		GridLayout glView = new GridLayout();
		glView.numColumns = 1;
		formView.getBody().setLayout(glView);
	}

	private void createMainBar(FormToolkit toolkitView, ScrolledForm formView) {

		Section sectionMenu = toolkitView.createSection(formView.getBody(),
				ExpandableComposite.TITLE_BAR | ExpandableComposite.EXPANDED);
		FontData fontData = new FontData("Arial", 14, SWT.BOLD);
		Font font = new Font(formView.getDisplay(), fontData);
		sectionMenu.setFont(font);
		
		sectionMenu.setText(searchString);

		sectionMenu.setBackground(new Color(null, 239, 244, 251));
		sectionMenu.setForeground(new Color(null, 13, 77, 163));
		sectionMenu.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		ToolBarManager toolBarManagerMenu = new ToolBarManager(SWT.FLAT);
		ToolBar toolbarMenu = toolBarManagerMenu.createControl(sectionMenu);

		ToolItem itemNewDoc = new ToolItem(toolbarMenu, SWT.NONE);
		itemNewDoc.setImage(StoredImages.getInstance().getMyImageRegistry()
				.get("ADD"));
		itemNewDoc.addListener(SWT.Selection, new EditListener(null, this,
				Singleton.getInstance().getUseCaseController(), -1));

		sectionMenu.setTextClient(toolbarMenu);
	}

	public static void showPopUpInfo(ToolItem item, ToolBar toolbar,
			Shell shell, String getAuthor, String getDate) {
		/* Code für die PopUpMenüs */
		Menu popupMenuInfo = new Menu(shell, SWT.POP_UP);

		MenuItem author = new MenuItem(popupMenuInfo, SWT.NONE);
		author.setEnabled(false);
		author.setText(getAuthor);

		MenuItem date = new MenuItem(popupMenuInfo, SWT.NONE);
		date.setEnabled(false);
		date.setText(getDate);

		Rectangle rect = item.getBounds();
		Point pt = new Point(rect.x, rect.y + rect.height);
		pt = toolbar.toDisplay(pt);
		popupMenuInfo.setLocation(pt.x, pt.y);
		popupMenuInfo.setVisible(true);
	}

	public void setEditorCom(IEditorPart editorCom) {
		this.editorCom = editorCom;
	}

	public IEditorPart getEditorCom() {
		return editorCom;
	}

	public void setEditorDoc(IEditorPart editorDoc) {
		this.editorDoc = editorDoc;
	}

	public IEditorPart getEditorDoc() {
		return editorDoc;
	}

	public IEditorPart getActiveEditor() {
		// TODO: NULL
		IEditorPart activeEditor = getSite().getPage().getActiveEditor();
		return activeEditor;
	}

	public void hideView() {
		getSite().getPage().hideView(CSADView.this);
	}

	public void showView() {
		try {
			getSite().getPage().showView("plug_inv01.views.CSADView");
		} catch (PartInitException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public IEditorPart refreshCommentEditor(IEditorPart editor, String file) {

		getSite().getWorkbenchWindow().getActivePage().closeEditor(editor,
				false);
		File fileToOpen = new File(file);
		if (fileToOpen.exists() && fileToOpen.isFile()) {
			IFileStore fileStore = EFS.getLocalFileSystem().getStore(
					fileToOpen.toURI());
			IWorkbenchPage page = PlatformUI.getWorkbench()
					.getActiveWorkbenchWindow().getActivePage();
			try {
				editor = IDE.openEditorOnFileStore(page, fileStore);
			} catch (PartInitException e) {
				// Put your exception handler here if you wish to
			}
		} else {
			// Do something if the file does not exist
			try {
				// Create file
				FileWriter fstream = new FileWriter(file);
				BufferedWriter out = new BufferedWriter(fstream);
				// Close the output stream
				out.close();
			} catch (Exception e) {// Catch exception if any
				System.err.println("Error: " + e.getMessage());
			}
			IFileStore fileStore = EFS.getLocalFileSystem().getStore(
					fileToOpen.toURI());
			IWorkbenchPage page = PlatformUI.getWorkbench()
					.getActiveWorkbenchWindow().getActivePage();
			try {
				editor = IDE.openEditorOnFileStore(page, fileStore);
			} catch (PartInitException e) {
				// Put your exception handler here if you wish to
			}
		}
		return editor;
	}
}